home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / perl5 / Apache / RPC / Server.pm next >
Encoding:
Perl POD Document  |  2008-04-10  |  32.3 KB  |  897 lines

  1. ###############################################################################
  2. #
  3. # This file copyright (c) 2001-2008 Randy J. Ray, all rights reserved
  4. #
  5. # See "LICENSE" in the documentation for licensing and redistribution terms.
  6. #
  7. ###############################################################################
  8. #
  9. #   $Id: Server.pm 343 2008-04-09 09:54:36Z rjray $
  10. #
  11. #   Description:    This package implements a RPC server as an Apache/mod_perl
  12. #                   content handler. It uses the RPC::XML::Server package to
  13. #                   handle request decoding and response encoding.
  14. #
  15. #   Functions:      handler
  16. #                   init_handler
  17. #                   new
  18. #                   get_server
  19. #                   version
  20. #                   INSTALL_DIR
  21. #                   list_servers
  22. #
  23. #   Libraries:      RPC::XML::Server
  24. #
  25. #   Global Consts:  $VERSION
  26. #
  27. ###############################################################################
  28.  
  29. package Apache::RPC::Server;
  30.  
  31. use 5.005;
  32. use strict;
  33.  
  34. use Socket;
  35. use File::Spec;
  36.  
  37. use Apache;
  38. use Apache::File; # For ease-of-use methods like set_last_modified
  39. use Apache::Constants ':common';
  40.  
  41. use RPC::XML 'bytelength';
  42. use RPC::XML::Server;
  43. @Apache::RPC::Server::ISA = qw(RPC::XML::Server);
  44.  
  45. BEGIN
  46. {
  47.     $Apache::RPC::Server::INSTALL_DIR = (File::Spec->splitpath(__FILE__))[1];
  48.     %Apache::RPC::Server::SERVER_TABLE = ();
  49. }
  50.  
  51. $Apache::RPC::Server::VERSION = '1.30';
  52.  
  53. sub version { $Apache::RPC::Server::VERSION }
  54.  
  55. sub INSTALL_DIR { $Apache::RPC::Server::INSTALL_DIR }
  56.  
  57. # Return a list (not list reference) of currently-known server objects,
  58. # represented as the text-keys from the hash table.
  59. sub list_servers { keys %Apache::RPC::Server::SERVER_TABLE }
  60.  
  61. # This is kinda funny, since I don't actually have a debug() method in the
  62. # RPC::XML::Server class at the moment...
  63. sub debug
  64. {
  65.     my $self = shift;
  66.     my $fmt  = shift;
  67.  
  68.     my $debug = ref($self) ? $self->SUPER::debug() : 1;
  69.  
  70.     $fmt && $debug &&
  71.         Apache::log_error(sprintf("%p ($$): $fmt",
  72.                                   (ref $self) ? $self : 0, @_));
  73.  
  74.     $debug;
  75. }
  76.  
  77. ###############################################################################
  78. #
  79. #   Sub Name:       handler
  80. #
  81. #   Description:    This is the default routine that Apache will look for
  82. #                   when we set this class up as a content handler.
  83. #
  84. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  85. #                   $class    in      scalar    Static name of the class we're
  86. #                                                 invoked in
  87. #                   $r        in      ref       Blessed Apache::Request object
  88. #
  89. #   Globals:        $DEF_OBJ
  90. #
  91. #   Returns:        Response code
  92. #
  93. ###############################################################################
  94. sub handler ($$)
  95. {
  96.     my $class = shift;
  97.     my $r = shift;
  98.  
  99.     my ($srv, $content, $resp, $hdrs, $hdrs_out, $compress, $length,
  100.         $do_compress, $com_engine, $parser, $me, $resp_fh, $c, $peeraddr,
  101.         $peerhost, $peerport);
  102.  
  103.     $srv = (ref $class) ? $class : $class->get_server($r);
  104.     $me = (ref($class) || $class) . '::handler';
  105.     unless (ref $srv)
  106.     {
  107.         $r->log_error("$me: PANIC! " . $srv);
  108.         return SERVER_ERROR;
  109.     }
  110.  
  111.     # Set the relevant headers
  112.     $hdrs_out = $r->headers_out;
  113.     $hdrs = $srv->response->headers;
  114.     for (keys %$hdrs) { $hdrs_out->{$_} = $hdrs->{$_} }
  115.     $r->content_type('text/xml');
  116.     # We're essentially done if this was a HEAD request
  117.     if ($r->header_only)
  118.     {
  119.         # These headers are either only sent for HEAD requests or are different
  120.         # enough to move here from the above block
  121.         $r->set_last_modified($srv->started);
  122.         $r->send_http_header;
  123.     }
  124.     elsif ($r->method eq 'POST')
  125.     {
  126.         # Step 1: Do we have the correct content-type?
  127.         return DECLINED unless ($r->header_in('Content-Type') =~ m|text/xml|i);
  128.         $compress = $srv->compress;
  129.         $do_compress = 1
  130.             if ($compress and
  131.                 ($r->header_in('Content-Encoding') || '') =~
  132.                  $srv->compress_re);
  133.  
  134.         # Step 2: Read the request in and convert it to a request object
  135.         # Note that this currently binds us to the Content-Length header a lot
  136.         # more tightly than I like. Expect to see this change sometime soon.
  137.         $length = $r->header_in('Content-Length');
  138.         $parser = $srv->parser->parse(); # Get the ExpatNB object
  139.         if ($do_compress)
  140.         {
  141.             # Spin up the compression engine
  142.             unless ($com_engine = Compress::Zlib::inflateInit())
  143.             {
  144.                 $r->log_error("$me: Unable to init the Compress::Zlib engine");
  145.                 return SERVER_ERROR;
  146.             }
  147.         }
  148.  
  149.         while ($length)
  150.         {
  151.             $r->read($content, ($length < 2048) ? $length : 2048);
  152.             $length -= length($content);
  153.             if ($do_compress)
  154.             {
  155.                 unless ($content = $com_engine->inflate($content))
  156.                 {
  157.                     $r->log_error("$me: Error inflating compressed data");
  158.                     return SERVER_ERROR;
  159.                 }
  160.             }
  161.             eval { $parser->parse_more($content); };
  162.             if ($@)
  163.             {
  164.                 $r->log_error("$me: XML parse error: $@");
  165.                 return SERVER_ERROR;
  166.             }
  167.         }
  168.  
  169.         eval { $content = $parser->parse_done; };
  170.         if ($@)
  171.         {
  172.             $r->log_error("$me: XML parse error at end: $@");
  173.             return SERVER_ERROR;
  174.         }
  175.  
  176.         # Step 3: Process the request and encode the outgoing response
  177.         # Dispatch will always return a RPC::XML::response object
  178.         {
  179.             # We set some short-lifespan localized keys on $srv to let the
  180.             # methods have access to client connection info
  181.             $c = $r->connection;
  182.             ($peerport, $peeraddr) = unpack_sockaddr_in($c->remote_addr);
  183.             $peerhost = inet_ntoa($peeraddr);
  184.             local $srv->{peeraddr} = $peeraddr;
  185.             local $srv->{peerhost} = $peerhost;
  186.             local $srv->{peerport} = $peerport;
  187.             $resp = $srv->dispatch($content);
  188.         }
  189.  
  190.         # Step 4: Form up and send the headers and body of the response
  191.         $r->no_cache(1);
  192.         $do_compress = 0; # Clear it
  193.         if ($compress and ($resp->length > $srv->compress_thresh) and
  194.             (($r->header_in('Accept-Encoding') || '') =~ $srv->compress_re))
  195.         {
  196.             $do_compress = 1;
  197.             $hdrs_out->{'Content-Encoding'} = $compress;
  198.         }
  199.         # Determine if we need to spool this to a file due to size
  200.         if ($srv->message_file_thresh and
  201.             $srv->message_file_thresh < $resp->length)
  202.         {
  203.             unless ($resp_fh = Apache::File->tmpfile)
  204.             {
  205.                 $r->log_error("$me: Error opening tmpfile");
  206.                 return SERVER_ERROR;
  207.             }
  208.  
  209.             # Now that we have it, spool the response to it. This is a
  210.             # little hairy, since we still have to allow for compression.
  211.             # And though the response could theoretically be HUGE, in
  212.             # order to compress we have to write it to a second temp-file
  213.             # first, so that we can compress it into the primary handle.
  214.             if ($do_compress)
  215.             {
  216.                 my $fh2 = Apache::File->tmpfile;
  217.                 unless ($fh2)
  218.                 {
  219.                     $r->log_error("$me: Error opening second tmpfile");
  220.                     return SERVER_ERROR;
  221.                 }
  222.  
  223.                 # Write the request to the second FH
  224.                 $resp->serialize($fh2);
  225.                 seek($fh2, 0, 0);
  226.  
  227.                 # Spin up the compression engine
  228.                 unless ($com_engine = Compress::Zlib::deflateInit())
  229.                 {
  230.                     $r->log_error("$me: Unable to initialize the " .
  231.                                   'Compress::Zlib engine');
  232.                     return SERVER_ERROR;
  233.                 }
  234.  
  235.                 # Spool from the second FH through the compression engine,
  236.                 # into the intended FH.
  237.                 my $buf = '';
  238.                 my $out;
  239.                 while (read($fh2, $buf, 4096))
  240.                 {
  241.                     unless (defined($out = $com_engine->deflate(\$buf)))
  242.                     {
  243.                         $r->log_error("$me: Compression failure in deflate()");
  244.                         return SERVER_ERROR;
  245.                     }
  246.                     print $resp_fh $out;
  247.                 }
  248.                 # Make sure we have all that's left
  249.                 unless (defined($out = $com_engine->flush))
  250.                 {
  251.                     $r->log_error("$me: Compression flush failure in deflate");
  252.                     return SERVER_ERROR;
  253.                 }
  254.                 print $resp_fh $out;
  255.  
  256.                 # Close the secondary FH. Rewinding the primary is done
  257.                 # later.
  258.                 close($fh2);
  259.             }
  260.             else
  261.             {
  262.                 $resp->serialize($resp_fh);
  263.             }
  264.             seek($resp_fh, 0, 0);
  265.  
  266.             $r->set_content_length(-s $resp_fh);
  267.             $r->send_http_header;
  268.             $r->send_fd($resp_fh);
  269.         }
  270.         else
  271.         {
  272.             # Treat the content strictly in-memory
  273.             $content = $resp->as_string;
  274.             $content = Compress::Zlib::compress($content) if $do_compress;
  275.             $r->set_content_length(length $content);
  276.             $r->send_http_header;
  277.             $r->print($content);
  278.         }
  279.     }
  280.     else
  281.     {
  282.         # Flag this as an error, since we don't permit the other methods
  283.         return DECLINED;
  284.     }
  285.  
  286.     OK;
  287. }
  288.  
  289. ###############################################################################
  290. #
  291. #   Sub Name:       init_handler
  292. #
  293. #   Description:    Provide a handler for the PerlChildInitHandler phase that
  294. #                   walks through the table of server objects and updates the
  295. #                   child_started time on each.
  296. #
  297. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  298. #                   $class    in      scalar    Calling class (this is a method
  299. #                                                 handler)
  300. #                   $r        in      ref       Apache reference object
  301. #
  302. #   Globals:        %SERVER_TABLE
  303. #
  304. #   Returns:        1
  305. #
  306. ###############################################################################
  307. sub init_handler ($$)
  308. {
  309.     my ($class, $r) = @_;
  310.  
  311.     $_->child_started(1) for (values %Apache::RPC::Server::SERVER_TABLE);
  312.  
  313.     OK;
  314. }
  315.  
  316. ###############################################################################
  317. #
  318. #   Sub Name:       new
  319. #
  320. #   Description:    Create a new server object, which is blessed into this
  321. #                   class and thus inherits most of the important bits from
  322. #                   RPC::XML::Server.
  323. #
  324. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  325. #                   $class    in      scalar    String or ref to ID the class
  326. #                   @argz     in      list      Type and relevance of args is
  327. #                                                 variable. See text.
  328. #
  329. #   Globals:        $INSTALL_DIR
  330. #
  331. #   Returns:        Success:    ref to new object
  332. #                   Failure:    error string
  333. #
  334. ###############################################################################
  335. sub new
  336. {
  337.     my $class = shift;
  338.     my @argz  = @_;
  339.  
  340.     my ($R, $servid, $prefix, $self, @dirs, @files, $ret, $no_def, $debug,
  341.         $do_auto, $do_mtime, %argz);
  342.  
  343.     # Convert @argz to a hash. As we consume arguments locally, we can delete
  344.     # them from the hash to avoid passing them along.
  345.     %argz = @argz;
  346.     $R      = $argz{apache} || Apache->server; delete $argz{apache};
  347.     $servid = $argz{server_id};                delete $argz{server_id};
  348.     $prefix = $argz{prefix};                   delete $argz{prefiz};
  349.     $argz{path} = $R->location unless $argz{path};
  350.     $servid = substr($argz{path}, 1) unless ($servid);
  351.  
  352.     #
  353.     # For these Apache-conf type of settings, something explicitly passed in
  354.     # via @argz is allowed to override the config file. So after pulling the
  355.     # value, it is only applied if the corresponding key doesn't already exist
  356.     #
  357.  
  358.     unless (exists $argz{debug})
  359.     {
  360.         # Is debugging requested?
  361.         $debug = $R->dir_config("${prefix}RpcDebugLevel") || 0;
  362.         $argz{debug} = $debug;
  363.     }
  364.  
  365.     # Check for disabling of auto-loading or mtime-checking
  366.     $do_auto  = $R->dir_config("${prefix}RpcAutoMethods") || 0;
  367.     $do_mtime = $R->dir_config("${prefix}RpcAutoUpdates") || 0;
  368.     foreach ($do_auto, $do_mtime) { $_ = (/yes/i) ? 1 : 0 }
  369.     $argz{auto_methods} = $do_auto  unless exists $argz{auto_methods};
  370.     $argz{auto_updates} = $do_mtime unless exists $argz{auto_updates};
  371.  
  372.     # If there is already an xpl_path, ensure that ours is on the top,
  373.     # otherwise add it.
  374.     if ($argz{xpl_path})
  375.     {
  376.         push(@{$argz{xpl_path}}, $Apache::RPC::Server::INSTALL_DIR);
  377.     }
  378.     else
  379.     {
  380.         $argz{xpl_path} = [ $Apache::RPC::Server::INSTALL_DIR ];
  381.     }
  382.  
  383.     # Create the object, ensuring that the defaults are not yet loaded:
  384.     my $Raux = (ref($R) eq 'Apache') ? $R->server : $R;
  385.     $self = $class->SUPER::new(no_default => 1, no_http => 1,
  386.                                path => $argz{path},
  387.                                host => $Raux->server_hostname || 'localhost',
  388.                                port => $Raux->port,
  389.                                %argz);
  390.     return $self unless (ref $self); # Non-ref means an error message
  391.     $self->started('set');
  392.  
  393.     # Check to see if we should suppress the default methods.
  394.     # The default is "no" (don't suppress the default methods), so use || in
  395.     # the evaluation in case neither were set.
  396.     $no_def = $argz{no_default} ? 1 :
  397.         (($R->dir_config("${prefix}RpcDefMethods") || '') =~ /no/i) ? 1 : 0;
  398.     unless ($no_def)
  399.     {
  400.         $self->add_default_methods(-except => 'status.xpl');
  401.         # This should find the Apache version of system.status instead
  402.         $self->add_method('status.xpl');
  403.     }
  404.  
  405.     # Determine what methods we are configuring for this server instance
  406.     @dirs    = split(/:/, $R->dir_config("${prefix}RpcMethodDir"));
  407.     @files   = split(/:/, $R->dir_config("${prefix}RpcMethod"));
  408.     # Load the directories first, then the individual files. This allows the
  409.     # files to potentially override entries in the directories.
  410.     for (@dirs)
  411.     {
  412.         $ret = $self->add_methods_in_dir($_);
  413.         return $ret unless ref $ret;
  414.     }
  415.     for (@files)
  416.     {
  417.         $ret = $self->add_method($_);
  418.         return $ret unless ref $ret;
  419.     }
  420.     if (@dirs)
  421.     {
  422.         # If there were any dirs specified for wholesale inclusion, add them
  423.         # to the search path for later reference.
  424.         $ret = $self->xpl_path;
  425.         unshift(@$ret, @dirs);
  426.         $self->xpl_path($ret);
  427.     }
  428.  
  429.     $Apache::RPC::Server::SERVER_TABLE{$servid} = $self;
  430.     $self;
  431. }
  432.  
  433. # Accessor similar to started() that has a time localized to this child process
  434. sub child_started
  435. {
  436.     my $self = shift;
  437.     my $set  = shift || 0;
  438.  
  439.     my $old = $self->{__child_started} || $self->started || 0;
  440.     $self->{__child_started} = time if $set;
  441.  
  442.     $old;
  443. }
  444.  
  445. ###############################################################################
  446. #
  447. #   Sub Name:       get_server
  448. #
  449. #   Description:    Retrieve the server object appropriate for this Server
  450. #                   instance passed in right after $self. If the second arg is
  451. #                   not a reference, assume they are asking for an existing
  452. #                   server by name.
  453. #
  454. #   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
  455. #                   $self     in      sc/ref    Object ref or class name
  456. #                   $r        in      ref       Apache interface object ref
  457. #
  458. #   Globals:        %SERVER_TABLE
  459. #
  460. #   Returns:        object ref, either specific or the default object. Sends a
  461. #                   text string if new() fails
  462. #
  463. ###############################################################################
  464. sub get_server
  465. {
  466.     my $self     = shift;
  467.     my $r        = shift;
  468.  
  469.     my ($prefix, $servid, $nocomp);
  470.  
  471.     if (ref $r)
  472.     {
  473.         # Presume $r to in fact be an Apache reference, and use it as such.
  474.         # If the server that matches this is already in the table, return it.
  475.         # If it isn't, create it from the information we have available.
  476.         $prefix = $r->dir_config('RPCOptPrefix') || '';
  477.         $servid = $r->dir_config("${prefix}RpcServer") || '<default>';
  478.         $nocomp = $r->dir_config('NoCompression') || '';
  479.  
  480.  
  481.         return $Apache::RPC::Server::SERVER_TABLE{$servid} ||
  482.             $self->new(apache      => $r,
  483.                        server_id   => $servid,
  484.                        prefix      => $prefix,
  485.                        no_compress => $nocomp,
  486.                        path        => $r->location);
  487.     }
  488.     else
  489.     {
  490.         # If $r isn't a reference, then this is likely been called as a class
  491.         # method to get the server object for a specific name. Thus, if it
  492.         # doesn't exist yet, we lack sufficient information to create it on
  493.         # the fly.
  494.         return $Apache::RPC::Server::SERVER_TABLE{$r} ||
  495.             "Error: No such server object '$r' known (yet)";
  496.     }
  497. }
  498.  
  499. 1;
  500.  
  501. __END__
  502.  
  503. =pod
  504.  
  505. =head1 NAME
  506.  
  507. Apache::RPC::Server - A subclass of RPC::XML::Server tuned for mod_perl
  508.  
  509. =head1 SYNOPSIS
  510.  
  511.     # In httpd.conf:
  512.     PerlModule Apache::RPC::Server
  513.     PerlSetVar RpcMethodDir /var/www/rpc:/usr/lib/perl5/RPC-shared
  514.     PerlChildInitHandler Apache::RPC::Server->init_handler
  515.     ...
  516.     <Location /RPC>
  517.         SetHandler perl-script
  518.         PerlHandler Apache::RPC::Server
  519.     </Location>
  520.     </Location /RPC-limited>
  521.         SetHandler perl-script
  522.         PerlHandler Apache::RPC::Server
  523.         PerlSetVar RPCOptPrefix RpcLimit
  524.         PerlSetVar RpcLimitRpcServer Limited
  525.         PerlSetVar RpcLimitRpcMethodDir /usr/lib/perl5/RPC-shared
  526.     </Location>
  527.  
  528.     # In the start-up Perl file:
  529.     use Apache::RPC::Server;
  530.  
  531. =head1 DESCRIPTION
  532.  
  533. The B<Apache::RPC::Server> module is a subclassing of B<RPC::XML::Server> that
  534. is tuned and designed for use within Apache with mod_perl.
  535.  
  536. Provided are phase-handlers for the general request-processing phase
  537. (C<PerlHandler>) and the child-process initialization phase
  538. (C<PerlChildInitHandler>). The module should be loaded either by inclusion in a
  539. server start-up Perl script or by directives in the server configuration file
  540. (generally F<httpd.con>). One loaded, the configuration file may assign the
  541. module to handle one or more given locations with the general set of
  542. C<E<lt>LocationE<gt>> directives and familiar options. Additional configuration
  543. settings specific to this module are detailed below.
  544.  
  545. Generally, externally-available methods are provided as files in the XML
  546. dialect explained in L<RPC::XML::Server>. A subclass derived from this class
  547. may of course use the methods provided by this class and its parent class for
  548. adding and manipulating the method table.
  549.  
  550. =head1 USAGE
  551.  
  552. This module is designed to be dropped in with little (if any) modification.
  553. The methods that the server publishes are provided by a combination of the
  554. installation files and Apache configuration values. Details on remote method
  555. syntax and semantics is covered in L<RPC::XML::Server>.
  556.  
  557. =head2 Methods
  558.  
  559. In addition to inheriting all the methods from B<RPC::XML::Server>, the
  560. following methods are either added or overloaded by B<Apache::RPC::Server>:
  561.  
  562. =over 4
  563.  
  564. =item handler
  565.  
  566. This is the default content-handler routine that B<mod_perl> expects when the
  567. module is defined as managing the specified location. This is provided as a
  568. I<method handler>, meaning that the first argument is either an object
  569. reference or a static string with the class name. This allows for other
  570. packages to easily subclass B<Apache::RPC::Server>.
  571.  
  572. This routine takes care of examining the incoming request, choosing an
  573. appropriate server object to actually process the request, and returning the
  574. results of the remote method call to the client.
  575.  
  576. =item init_handler
  577.  
  578. This is another Apache-level handler, this one designed for installation as a
  579. C<PerlChildInitHandler>. At present, its only function is to iterate over all
  580. server object currently in the internal tables and invoke the C<child_started>
  581. method (detailed below) on each. Setting this handler assures that each child
  582. has a correct impression of when it started as opposed to the start time of the
  583. server itself.
  584.  
  585. Note that this is only applied to those servers known to the master Apache
  586. process. In most cases, this will only be the default server object as
  587. described above. That is because of the delayed-loading nature of all servers
  588. beyond the default, which are likely only in child-specific memory. There are
  589. some configuration options described in the next section that can affect and
  590. alter this.
  591.  
  592. =item new(HASH)
  593.  
  594. This is the class constructor. It calls the superclass C<new> method, then
  595. performs some additional steps. These include installing the default methods
  596. (which includes an Apache-specific version of C<system.status>), adding the
  597. installation directory of this module to the method search path, and adding any
  598. directories or explicitly-requested methods to the server object.
  599.  
  600. The arguments to the constructor are regarded as a hash table (not a hash
  601. reference), and are mostly passed unchanged to the constructor for
  602. B<RPC::XML::Server>. Three parameters are of concern to this class:
  603.  
  604. =over 8
  605.  
  606. =item apache
  607.  
  608. The value associated with this key is a reference to an B<Apache> request
  609. object. If this is not passed, then it is assumed that this is being called in
  610. the start-up phase of the server and the value returned from C<Apache->server>
  611. (see L<Apache>) is used.
  612.  
  613. =item server_id
  614.  
  615. This provides the server ID string for the RPC server (not to be confused with
  616. the Apache server) that is being configured.
  617.  
  618. =item prefix
  619.  
  620. The prefix is used in retrieving certain configuration settings from the Apache
  621. configuration file.
  622.  
  623. =back
  624.  
  625. The server identification string and prefix concepts are explained in more
  626. detail in the next section. See L<RPC::XML::Server> for a full list of what
  627. additional arguments may be passed to B<new> for eventual proxy to the parent
  628. class constructor.
  629.  
  630. =item child_started([BOOLEAN])
  631.  
  632. This method is very similar to the C<started> method provided by
  633. B<RPC::XML::Server>. When called with no argument or an argument that evaluates
  634. to a false value, it returns the UNIX-style time value of when this child
  635. process was started. Due to the child-management model of Apache, this may very
  636. well be different from the value returned by C<started> itself. If given an
  637. argument that evaluates as true, the current system time is set as the new
  638. child-start time.
  639.  
  640. If the server has not been configured to set this at child initialization, then
  641. the main C<started> value is returned. The name is different so that a child
  642. may specify both server-start and child-start times with clear distinction.
  643.  
  644. =item get_server(APACHEREQ|STRING)
  645.  
  646. Get the server object that corresponds to the argument passed. If the argument
  647. is a reference to an B<Apache> request object, use it to determine the name
  648. (by path, etc.) and return that object. If the parameter is not a reference,
  649. it is assumed to be the specific name desired.
  650.  
  651. If the requested server object does not yet exist, an attempt will be made to
  652. create it and add it to the internal table. The newly-created object is then
  653. returned.
  654.  
  655. =item list_servers
  656.  
  657. Return a list of the I<names> used for all the current server instances. Does
  658. not return the server objects themselves (use B<get_server>, above, for that).
  659.  
  660. =item version
  661.  
  662. This method behaves exactly like the B<RPC::XML::Server> method, except that
  663. the version string returned is specific to this module instead.
  664.  
  665. =item INSTALL_DIR
  666.  
  667. As with B<version>, this is an overload of the parent-class static method that
  668. returns the installation directory of this particular module.
  669.  
  670. =back
  671.  
  672. =head2 Apache configuration semantics
  673.  
  674. In addition to the known directives such as C<PerlHandler> and
  675. C<PerlChildInitHandler>, configuration of this system is controlled through a
  676. variety of settings that are manipulated with the C<PerlSetVar> and
  677. C<PerlAddVar> directives. These variables are:
  678.  
  679. =over 4
  680.  
  681. =item RPCOptPrefix [STRING]
  682.  
  683. Sets a prefix string to be applied to all of the following names before trying
  684. to read their values. Useful for setting within a C<E<lt>LocationE<gt>> block
  685. to ensure that no settings from a higher point in the hierarchy influence the
  686. server being defined.
  687.  
  688. =item RpcServer [STRING]
  689.  
  690. Specify the name of the server to use for this location. If not passed, then
  691. the default server is used. This server may also be explicitly requested by the
  692. name "C<C<E<lt>defaultE<gt>>>". If more than one server is going to be created
  693. within the same Apache environment, this setting should always be used outside
  694. the default area so that the default server is not loaded down with extra
  695. method definitions. If a sub-location changes the default server, those changes
  696. will be felt by any location that uses that server.
  697.  
  698. Different locations may share the same server by specifying the name with this
  699. variable. This is useful for managing varied access schemes, traffic analysis,
  700. etc.
  701.  
  702. =item RpcMethodDir [DIRECTORY]
  703.  
  704. This variable specifies directories to be scanned for method C<*.xpl>
  705. files. To specify more than one directory, separate them with "C<:>" just as
  706. with any other directory-path expression. All directories are kept (in the
  707. order specified) as the search path for future loading of methods.
  708.  
  709. =item RpcMethod [FILENAME]
  710.  
  711. This is akin to the directory-specification option above, but only provides a
  712. single method at a time. It may also have multiple values separated by
  713. colons. The method is loaded into the server table. If the name is not an
  714. absolute pathname, then it is searched for in the directories that currently
  715. comprise the path. The directories above, however, have not been added to the
  716. search path yet. This is because these directives are processed immediately
  717. after the directory specifications, and thus do not need to be searched. This
  718. directive is designed to allow selective overriding of methods in the
  719. previously-specified directories.
  720.  
  721. =item RpcDefMethods [YES|NO]
  722.  
  723. If specified and set to "no" (case-insensitive), suppresses the loading of the
  724. system default methods that are provided with this package. The absence of this
  725. setting is interpreted as a "yes", so explicitly specifying such is not needed.
  726.  
  727. =item RpcAutoMethods [YES|NO]
  728.  
  729. If specified and set to "yes", enables the automatic searching for a requested
  730. remote method that is unknown to the server object handling the request. If
  731. set to "no" (or not set at all), then a request for an unknown function causes
  732. the object instance to report an error. If the routine is still not found, the
  733. error is reported. Enabling this is a security risk, and should only be
  734. permitted by a server administrator with fully informed acknowledgement and
  735. consent.
  736.  
  737. =item RpcAutoUpdates [YES|NO]
  738.  
  739. If specified and set to "yes", enables the checking of the modification time
  740. of the file from which a method was originally loaded. If the file has
  741. changed, the method is re-loaded before execution is handed off. As with the
  742. auto-loading of methods, this represents a potential security risk, and should
  743. only be permitted by a server administrator with fully informed
  744. acknowledgement and consent.
  745.  
  746. =back
  747.  
  748. =head2 Specifying methods to the server(s)
  749.  
  750. Methods are provided to an B<Apache::RPC::Server> object in three ways:
  751.  
  752. =over 4
  753.  
  754. =item Default methods
  755.  
  756. Unless suppressed by a C<RpcDefMethods> option, the methods shipped with this
  757. package are loaded into the table. The B<Apache::RPC::Server> objects get a
  758. slightly different version of C<system.status> than the parent class does.
  759.  
  760. =item Configured directories
  761.  
  762. All method files (those ending in a suffix of C<*.xpl>) in the directories
  763. specified in the relevant C<RpcMethodDir> settings are read next. These
  764. directories are also (after the next step) added to the search path the object
  765. uses.
  766.  
  767. =item By specific inclusion
  768.  
  769. Any methods specified directly by use of C<RpcMethod> settings are loaded
  770. last. This allows for them to override methods that may have been loaded from
  771. the system defaults or the specified directories.
  772.  
  773. =back
  774.  
  775. If a request is made for an unknown method, the object will first attempt to
  776. find it by searching the path of directories that were given in the
  777. configuration as well as those that are part of the system (installation-level
  778. directories). If it is still not found, then an error is reported back to the
  779. requestor. By using this technique, it is possible to add methods to a running
  780. server without restarting it. It is a potential security hole, however, and it
  781. is for that reason that the previously-documented C<RpcAutoMethods> setting is
  782. provided.
  783.  
  784. =head2 Usage Within <Perl> Sections
  785.  
  786. To truly unlock the power of having the RPC server attached to a B<mod_perl>
  787. environment, the application and configuration of the server should be done
  788. within Perl-configuration blocks on the Apache server itself.
  789.  
  790. In doing this, two immediate benefits are gained:
  791.  
  792. =over 4
  793.  
  794. =item (1)
  795.  
  796. The rpc-server object gets created in the master Apache process, rather than
  797. within each child as a side-effect of the first request.  Especially in cases
  798. where there are going to be more than one server in use within the Apache
  799. environment, this boosts performance by allowing newly-created children to
  800. already have the server object and method table readily available.
  801.  
  802. =item (2)
  803.  
  804. It becomes possible to exert more detailed control over the creation and
  805. configuration of each server object. Combining the B<get_method> and
  806. B<add_method> operations permits "sharing" (of a sort) of methods between
  807. server objects. Recall from the B<RPC::XML::Server> documentation that, when a
  808. method is invoked, the first argument is the server object that is marshalling
  809. it.
  810.  
  811. =back
  812.  
  813. The following example illustrates these concepts in a fairly simple
  814. environment:
  815.  
  816.     # In httpd.conf:
  817.     <Perl>
  818.  
  819.     # First, create and configure some Apache::RPC::Server objects
  820.  
  821.     # One regular one, with the standard settings:
  822.     $main::defobj = Apache::RPC::Server->new(path         => '/RPC',
  823.                                              auto_methods => 1,
  824.                                              auto_updates => 1);
  825.     # One version without the default methods, and no auto-actions
  826.     $main::secobj = Apache::RPC::Server->new(no_default => 1,
  827.                                              path => '/rpc-secured');
  828.  
  829.     # Imagine that add_method and/or add_methods_in_dir has been used to
  830.     # add to the methods tables for those objects. Now assign them to
  831.     # locations managed by Apache:
  832.     $Location{'/RPC'} =
  833.         {
  834.             SetHandler  => 'perl-script',
  835.             PerlHandler => '$main::defobj'
  836.         };
  837.     $Location{'/rpc-secure'} =
  838.         {
  839.             SetHandler   => 'perl-script',
  840.             PerlHandler  => '$main::secobj',
  841.             AuthUserFile => '/etc/some_file',
  842.             AuthType     => 'Basic',
  843.             AuthName     => 'SecuredRPC',
  844.             'require'    => 'valid-user'
  845.         };
  846.  
  847.     </Perl>
  848.  
  849. Note that the assignment of the C<PerlHandler> value was a string
  850. representation of the object reference itself. B<mod_perl> performs a sort of
  851. "thaw" of this string when the location is accessed. Since this class
  852. implements itself as a I<method handler>, this causes the C<handler()> method
  853. for each of the locations to be handed the B<Apache::RPC::Server> object
  854. directly. Note also that the value assigned to C<PerlHandler> cannot be a
  855. lexical variable, or it will be out of scope when the handler is called.
  856.  
  857. =head1 DIAGNOSTICS
  858.  
  859. All methods return some type of reference on success, or an error string on
  860. failure. Non-reference return values should always be interpreted as errors
  861. unless otherwise noted.
  862.  
  863. Where appropriate, the C<log_error> method from the B<Apache> package
  864. is called to note internal errors.
  865.  
  866. =head1 CAVEATS
  867.  
  868. This began as a reference implementation in which clarity of process and
  869. readability of the code took precedence over general efficiency. It is now
  870. being maintained as production code, but may still have parts that could be
  871. written more efficiently.
  872.  
  873. =head1 CREDITS
  874.  
  875. The B<XML-RPC> standard is Copyright (c) 1998-2001, UserLand Software, Inc.
  876. See <http://www.xmlrpc.com> for more information about the B<XML-RPC>
  877. specification.
  878.  
  879. =head1 LICENSE
  880.  
  881. This module and the code within are released under the terms of the Artistic
  882. License 2.0
  883. (http://www.opensource.org/licenses/artistic-license-2.0.php). This code may
  884. be redistributed under either the Artistic License or the GNU Lesser General
  885. Public License (LGPL) version 2.1
  886. (http://www.opensource.org/licenses/lgpl-license.php).
  887.  
  888. =head1 SEE ALSO
  889.  
  890. L<RPC::XML::Server>, L<RPC::XML>
  891.  
  892. =head1 AUTHOR
  893.  
  894. Randy J. Ray <rjray@blackperl.com>
  895.  
  896. =cut
  897.